package chatBot.service.impl;


import chatBot.entity.User;
import chatBot.repository.UserRepository;
import chatBot.service.WeChatService;
import chatBot.utils.JwtUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static chatBot.constans.RedisConstant.USER_TOKEN_KEY;
import static chatBot.constans.RedisConstant.USER_TOKEN_TTL;

/**
 * @Author 余俊杰
 * 2024/8/18 15:07
 */

@Service
public class WeChatServiceImpl implements WeChatService {

    @Value("${wechat.appId}")
    private String appId;

    @Value("${wechat.appSecret}")
    private String appSecret;

    private final RestTemplate restTemplate = new RestTemplate();

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserRepository userRepository;

    /**
     * SpringSecurity需要的一些类，加密存储，对password进行编码再存入数据库，
     * 登录时先加密再进行比较
     * 将基于此创建AuthenticationManager类
     */
    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();


    @Override
    public String getOpenIdFromCode(String code) throws IOException {
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", appId, appSecret, code);
        String response = restTemplate.getForObject(url, String.class);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(response);
        return rootNode.path("openid").asText();
    }

    @Override
    public User login(String code, String username) throws IOException {
        String openId = getOpenIdFromCode(code);
        Optional<User> optionalUser = userRepository.findByOpenId(openId);
        if (optionalUser.isPresent()) {
            // 生成用户的TOKEN并返回，Redis中存入该用户的信息与token
            String token = JwtUtil.createToken(optionalUser.get().getUserId());
            saveUserJwt2Redis(optionalUser.get(), token);
            return optionalUser.get();
        } else {
//            沒找到就綁定
            User newUser = new User();
            newUser.setUserId(IdWorker.getId());
            newUser.setOpenId(openId);
            newUser.setUserName(username);
            newUser.setUserEmail("defaultEmail@qq.com");
            newUser.setUserPassword("defaultPassword");
            return userRepository.save(newUser);
        }
    }

    @Override
    public Map<String,Object> bind(String openId, String email, String password) {
        User user = userRepository.findByOpenId(openId).orElseThrow(() -> new RuntimeException("User not found"));
        user.setUserEmail(email);
        user.setUserPassword(passwordEncoder.encode(password));
        user.setUserTokenCount(100);
        // 生成用户的TOKEN并返回，Redis中存入该用户的信息与token
        String token = JwtUtil.createToken(user.getUserId());
        saveUserJwt2Redis(user, token);
        User save = userRepository.save(user);
        // 构造返回结果
        Map<String, Object> map = new HashMap<>(4);
        map.put("token", token);
        map.put("user", user);

        return map;
    }

    public void saveUserJwt2Redis(User user, String token) {
        stringRedisTemplate.opsForValue().set(USER_TOKEN_KEY + user.getUserId(), token, USER_TOKEN_TTL, TimeUnit.MINUTES);
    }




}
